package com.puboot.module.admin.media;

import com.alibaba.fastjson.JSON;
import com.puboot.common.util.*;
import com.puboot.module.admin.model.BizFile;
import com.puboot.module.admin.service.BizFileService;
import com.puboot.module.admin.vo.UploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @Description
 * @Author 申紫微
 * @Data 2020-02-14 10:15:02
 * @Version 1.0
 */
@Controller
@Slf4j
public class UploadAction extends BaseAction{


    public static final String allowFile = "jpg,gif,png,jpeg|zip,rar,7z|txt,doc,docx,xls,xlsx,pdf|apk,wgt,ipa|mp4,flv";
    public static final String allowImg = "jpg,gif,png,jepg";

    @Autowired
    private BizFileService fileService;

    @Value("${ftp.server.path}")
    private String uploadPath;
    @Value("${ftp.open}")
    private String ftpOpenStatus;

    public String getRealWebPath(){return request.getServletContext().getRealPath("/"); }

    /**
     * @Author 申紫微
     * @Description 单文件上传
     * @Date 14:04 2020/2/14
     * @Param [multipartRequest]
     * @return java.lang.String
     **/
    @PostMapping(value = "/upload")
    @ResponseBody
    public String upload(MultipartHttpServletRequest multipartRequest){

        Map<String, MultipartFile> multipartFileMap = multipartRequest.getFileMap();
        // 只支持单个文件上传
        Set<Map.Entry<String, MultipartFile>> entrySet = multipartFileMap.entrySet();
        Iterator<Map.Entry<String, MultipartFile>> entrySetIt = entrySet.iterator();
        if(entrySetIt.hasNext()){
            Map.Entry<String, MultipartFile> entry = entrySetIt.next();
            //获取单个文件
            MultipartFile file = entry.getValue();
            // 单个文件上传
            UploadResponse uploadResponse = singleUpload(file);
            return JSON.toJSONString(uploadResponse);
        }
        //没有上传任何文件
        return JSON.toJSONString(UploadResponse.Error.NONE);
    }

    @PostMapping(value = "/uploadArticleImg")
    @ResponseBody
    public Map<Object, Object> uploadArticleImg(MultipartHttpServletRequest multipartRequest){
        Map<Object, Object> resultMap = new HashMap<>();
        Map<String, MultipartFile> multipartFileMap = multipartRequest.getFileMap();
        // 只支持单个文件上传
        Set<Map.Entry<String, MultipartFile>> entrySet = multipartFileMap.entrySet();
        Iterator<Map.Entry<String, MultipartFile>> entrySetIt = entrySet.iterator();
        if(entrySetIt.hasNext()){
            Map.Entry<String, MultipartFile> entry = entrySetIt.next();
            //获取单个文件
            MultipartFile file = entry.getValue();
            // 单个文件上传
            UploadResponse uploadResponse = singleUpload(file);
            Integer status = uploadResponse.getStatus();
            if(status == 200){
                resultMap.put("uploaded",true);
                String url = uploadResponse.getUrl();
                resultMap.put("url","/images/"+uploadResponse.getId()+"?w=200&h=200");
            }else{
                resultMap.put("uploaded",false);
                String url = uploadResponse.getUrl();
                resultMap.put("url","");
            }
            return resultMap;
        }
        //没有上传任何文件
        return Collections.emptyMap();
    }

    /**
     * @Author 申紫微
     * @Description 单文件上传
     * @Date 14:02 2020/2/14
     * @Param [file]
     * @return com.puboot.module.admin.vo.UploadResponse
     **/
    public UploadResponse singleUpload(MultipartFile file){
        //获取文件基本信息
        BizFile dbFile = getFileAInfo(file);
        // 不允许上传文件直接返回
        if(!StringUtils.containsIgnoreCase(allowFile, dbFile.getFileType())){
            log.warn("文件不允许上传");
            return new UploadResponse(null,CoreConst.FAIL_CODE,UploadResponse.Error.ILLEGALEXTENSION);
        }
        try {
            // 本地上传文件
            if("false".equals(ftpOpenStatus)) {
                localUpload(file, dbFile);
            } else {
                FTPUpload(file, dbFile);
            }
            // 保存文件信息到数据库
            int i = fileService.saveFile(dbFile);
            if(i < 0){
                log.error("文件上传成功，但数据保存失败");
                return null;
            }
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return null;
        }
        return new UploadResponse(dbFile.getId(),dbFile.getFileAddr(), dbFile.getFileOriginalName(), dbFile.getFileType(), dbFile.getFileAddr(), CoreConst.SUCCESS_CODE);
    }

    /**
     * @Author 申紫微
     * @Description 本地文件上传，上传成功则设置路径，失败则抛出异常
     * @Date 13:49 2020/2/14
     * @Param [file, dbFile]
     * @return void
     **/
    private void localUpload(MultipartFile file,BizFile dbFile) throws IOException {

        //获取上传绝对路径
        String filePath = UploadUtil.getUploadPath(this.uploadPath + File.separator + "upload" + File.separator);
        //生成上传目录
        FileUtil.createDirs(filePath);
        log.info("文件开始上传");
        log.info("文件上传的路径:{}",filePath);
        file.transferTo(new File(filePath,dbFile.getFileName()));

        //设置文件的路径
        //因为ftp上传和本地文件上传处理方式不一样 所以在这里进行维护
        String webRequestPath = filePath.concat(dbFile.getFileName()).substring(uploadPath.length());
//        dbFile.setFileAddr(webRequestPath);
        String concat = filePath.concat(webRequestPath);
        log.info("=====>拼接路径：{}",concat);
        dbFile.setFileAddr(webRequestPath);
        log.info("====>数据库存储路径：{}",webRequestPath);
        log.info("文件上传成功");

    }

    /**
     * @Author 申紫微
     * @Description FTP 远程上传
     * @Date 14:10 2020/2/14
     * @Param [file, dbFile]
     * @return void
     **/
    private void FTPUpload(MultipartFile file, BizFile dbFile) throws IOException {

        //临时存放
        String path = request.getSession().getServletContext().getRealPath("upload");

        String filePath = "/suning/";
        log.info("文件开始上传");
        log.info("文件将要上传的路径:{}",filePath);

        ArrayList<File> arrayList = new ArrayList<>();
        FileUtil.createDirs(path);
        File tmpFile = new File(path + File.separator + dbFile.getFileName());

        file.transferTo(tmpFile);
        arrayList.add(tmpFile);
        if(FTPUtil.upload(filePath,arrayList)){
            //上传成功
            String webRequestPath = filePath.concat(dbFile.getFileName());
            dbFile.setFileAddr(webRequestPath);
            log.info("文件上传成功");
        }else{
            throw  new RuntimeException("文件上传失败");
        }
        tmpFile.delete();
    }

    /**
     * @Author 申紫微
     * @Description 获取文件信息
     * @Date 11:17 2020/2/14
     * @Param [file]
     * @return com.puboot.module.admin.model.BizFile
     **/
    private BizFile getFileAInfo(MultipartFile file){

        //获取文件信息
        String fileName = file.getOriginalFilename();
        long fileSize = file.getSize();
        //获取文件后缀名
        String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);

        BizFile bizFile = new BizFile();
        bizFile.setFid(UUIDUtil.getUniqueIdByUUId());
        bizFile.setFileOriginalName(fileName.substring(0,fileName.lastIndexOf(".")));
        bizFile.setFileName(UploadUtil.getNewFileName(fileName));
        bizFile.setFileType(suffix.toLowerCase());
        bizFile.setFileDownloads(0);
        bizFile.setCreateTime(new Date());
        
        log.debug("文件信息：", fileSize, fileSize / 1024);
        log.debug("源名称：{}", fileName);
        log.debug("大小：{}", fileSize);
        log.debug("新名称：{}", bizFile.getFileName());
        return bizFile;
    }

    public static void main(String[] args) {

        String str =  "f:/ftpfile\\upload\\2020/02/14/31jpg";
        String substring = str.substring(2, str.length());

        log.info("#################:{}",substring);

    }

}
